/**  
* Copyright (c) 2009, Noel Lynch All rights reserved. Redistribution and use  
* in source and binary forms, with or without modification, are permitted  
* provided that the following conditions are met: Redistributions of source  
* code must retain the above copyright notice, this list of conditions and the  
* following disclaimer. Redistributions in binary form must reproduce the above  
* copyright notice, this list of conditions and the following disclaimer in the  
* documentation and/or other materials provided with the distribution. Neither  
* the name of Noel Lynch nor the names of contributors may be used to  
* endorse or promote products derived from this software without specific prior  
* written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A  
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR  
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
*/
// created by noellynch
// Oct 1, 2009

package com.sceneworker.util.jme.coderep;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;

import com.jme.scene.Node;
import com.jme.scene.state.CullState;
import com.myjavautils.GenericUtils;

public class JMECodeRep {

	private		ArrayList<String>		mcla_classList;
	private		Stack<String>			mcla_variableStack;
	
	static		private		HashMap<Class<?>, ICodeRep>		mcla_mappings;
	
	
	private	JMECodeRep() {
		mcla_classList = new ArrayList<String>();
		mcla_variableStack = new Stack<String>();
		if(mcla_mappings == null) {
			initialiseMappings();
		}
	}
	
	private	void	initialiseMappings() {
		mcla_mappings = new HashMap<Class<?>, ICodeRep>();
		
		mcla_mappings.put(Node.class, new NodeCodeRep());
		mcla_mappings.put(CullState.class, new CullStateRep());
	}
	
	private	void	checkImport(Class<?> cl_class) {
		if(!classInClassList(cl_class.getName())) {
			mcla_classList.add(cl_class.getName());
		}
	}
	
	private	boolean		classInClassList(String str_package) {
		for(String lstr_p : mcla_classList) {
			if(lstr_p.equals(str_package)) {
				return true;
			}
		}
		
		return false;
	}
	
	public	String		process(Object cl_obj) {
		System.out.println("processing " + cl_obj.getClass().getName());
		String 	lstr_out = "";
		
		ICodeRep		lcl_rep = null;
		Class<?>		lcl_class = cl_obj.getClass();
		
		while((lcl_rep == null) && (lcl_class != null)) {
			lcl_rep = mcla_mappings.get(lcl_class);
			if(lcl_rep == null) {
				lcl_class = lcl_class.getSuperclass();
			}
		}
		
		if(lcl_rep != null) {
			checkImport(lcl_class);
			//System.out.println(lcl_rep.getClass().getName() + " for " + lcl_class.getName());
			lstr_out += lcl_rep.ctor(this, cl_obj, lcl_class);
			lstr_out += lcl_rep.populate(this, cl_obj);
			lstr_out += lcl_rep.process(this, cl_obj);
			lstr_out += lcl_rep.finish(this, cl_obj);
		}
		
		return lstr_out;
	}
	
	public	ICodeRep	getRep(Class<?> cl_class) {
		ICodeRep		lcl_rep = mcla_mappings.get(cl_class);
		return lcl_rep;
	}
	
	public	Stack<String>		getVariableStack() {
		return mcla_variableStack;
	}
	
	private	void	exportSceneToCodeRep(Object cl_obj) {
		File			lcl_f = GenericUtils.getAFile(null, true, true);
		if(lcl_f == null) {
			return;
		}
		
		String 	lstr_rep = process(cl_obj);
		
		String 	lstr_importStatement = "";
		for(String lstr_import : mcla_classList) {
			lstr_importStatement += "import " + lstr_import + ";\n";
		}
		
		String		lstr_fn = "\n\npublic void initScene() {\n" + lstr_rep + "}";
		lstr_fn.replace("\n", "\n\t");
		System.out.println(lstr_importStatement + lstr_fn);
	}
	
	static	public	void	doExport(Object cl_obj) {
		JMECodeRep		lcl_rep = new JMECodeRep();
		lcl_rep.exportSceneToCodeRep(cl_obj);
	}
	
	public	interface	ICodeRep {
		String		ctor(JMECodeRep cl_rep, Object cl_obj, Class<?> cl_class);
		String		populate(JMECodeRep cl_rep, Object cl_obj);
		String		process(JMECodeRep cl_rep, Object cl_obj);
		String		finish(JMECodeRep cl_rep, Object cl_obj);
	}
	
	static	public	String		method(String str_var, String str_method, String... stra_params) {
		String 	lstr_temp = str_var + "." + str_method + "(";
		
		if(stra_params.length == 0) {
			return lstr_temp += ")";
		}
		
		
		for(int li_index = 0; li_index < (stra_params.length - 1); li_index++) {
			lstr_temp += stra_params[li_index] + ", ";
		}
		
		
		lstr_temp += stra_params[stra_params.length - 1] + ");\n";
		
		return lstr_temp;
	}
	
	static	public	String	construct(String str_var, String str_type, String... stra_params) {
		String 	lstr_temp = str_type + " " + str_var + " = new " + str_type + "(";
		
		if(stra_params.length == 0) {
			return lstr_temp += ")";
		}
		
		
		for(int li_index = 0; li_index < (stra_params.length - 1); li_index++) {
			lstr_temp += stra_params[li_index] + ", ";
		}
		
		lstr_temp += stra_params[stra_params.length - 1] + ");\n";
		
		return lstr_temp;
	}
	
	static	public	String	renderStateConstruct(String str_var, Class<?> cl_rsClass) {
		return cl_rsClass.getSimpleName() + " " + str_var + " = com.jme.system.DisplaySystem.getDisplaySystem().getRenderer().create" + cl_rsClass.getSimpleName() + "();\n";
	}
}
